package ma.ensao.evalmetrics.controller.metrics;

import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.body.BodyDeclaration;
import japa.parser.ast.body.ClassOrInterfaceDeclaration;
import japa.parser.ast.body.MethodDeclaration;
import japa.parser.ast.visitor.VoidVisitorAdapter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import ma.ensao.evalmetrics.controller.MethodManager;
import ma.ensao.evalmetrics.model.ResultMethod;

import org.apache.commons.lang3.StringUtils;

import com.opensymphony.xwork2.ActionSupport;

public class MethodMetrics extends ActionSupport{
		
	List<ResultMethod> methods;
	ResultMethod currentMethod;
	String pack ,classe; 
	private Long id;
	private MethodManager methodmanager;
	private List<ResultMethod> resultmethod;
	private double mark;
	
	public MethodMetrics(){
		methods = new ArrayList<ResultMethod>() ;
		
	}
	
	public List<ResultMethod> read(File file){
		
		CompilationUnit cu = null;
		try {

			cu = JavaParser.parse(file);
			pack = cu.getPackage().getName().toString();
	        new MethodVisitor().visit(cu, null);
		} catch (ParseException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
		return methods;
	}
	
private class MethodVisitor extends VoidVisitorAdapter {
    	
    	int cyclo ;
    	int sloc;
    	
    	@Override
        public void visit(ClassOrInterfaceDeclaration n, Object arg) {
    		super.visit(n, arg);
    		List<BodyDeclaration> members = n.getMembers();
    		classe = n.getName();
    		for(int i=0;i<members.size();i++){
    			if(MethodDeclaration.class.equals(members.get(i).getClass())){
    				currentMethod=new  ResultMethod();
    				currentMethod.setClasse(pack+"."+classe);
    				visit((MethodDeclaration) members.get(i));
    			}
    		}
    		
    	}

		
        public void visit(MethodDeclaration m) {
            
        	cyclo=1;
        	sloc=0;

        	currentMethod.setNamemethode(m.getName());
        	String modif = "";
        	int mod = m.getModifiers();
        	if(japa.parser.ast.body.ModifierSet.isPublic(mod)){
        		modif+="public ";
        	}
        	if(japa.parser.ast.body.ModifierSet.isPrivate(mod)){
        		modif+="private ";
        	}
        	if(japa.parser.ast.body.ModifierSet.isProtected(mod)){
        		modif+="protected ";
        	}
        	if(japa.parser.ast.body.ModifierSet.isAbstract(mod)){
        		modif+="abstract ";
        	}
        	if(japa.parser.ast.body.ModifierSet.isFinal(mod)){
        		modif+="final ";
        	}
        	if(japa.parser.ast.body.ModifierSet.isSynchronized(mod)){
        		modif+="synchronized ";
        	}
        	if(japa.parser.ast.body.ModifierSet.isStatic(mod)){
        		modif+="static ";
        	}
        	currentMethod.setType(modif);
        	
        	if(m.getBeginLine() != m.getEndLine()){
            String body=m.getBody().toString();
            sloc = body.split("\r\n|\r|\n").length;
            
	        
            int count;
            count = StringUtils.countMatches(body, "for (");
            cyclo +=count;
            count = StringUtils.countMatches(body, "for(");
            cyclo +=count;
            count = StringUtils.countMatches(body, "if (");
            cyclo +=count;
            count = StringUtils.countMatches(body, "if(");
            cyclo +=count;
            count = StringUtils.countMatches(body, "case ");
            cyclo +=count;
            count = StringUtils.countMatches(body, "default:");
            cyclo +=count;
            count = StringUtils.countMatches(body, "default :");
            cyclo +=count;
            count = StringUtils.countMatches(body, "else {");
            cyclo +=count;
            count = StringUtils.countMatches(body, "else{");
            cyclo +=count;
            count = StringUtils.countMatches(body, "while (");
            cyclo +=count;
            count = StringUtils.countMatches(body, "while(");
            cyclo +=count;
            count = StringUtils.countMatches(body, "break ;");
            cyclo +=count;
            count = StringUtils.countMatches(body, "break;");
            cyclo +=count;
            count = StringUtils.countMatches(body, "do (");
            cyclo +=count;
            count = StringUtils.countMatches(body, "do(");
            cyclo +=count;
            count = StringUtils.countMatches(body, "switch (");
            cyclo +=count;
            count = StringUtils.countMatches(body, "switch(");
            cyclo +=count;
            count = StringUtils.countMatches(body, "try");
            cyclo +=count;
            count = StringUtils.countMatches(body, "catch");
            cyclo +=count;
           
            
        	}
            currentMethod.setVg(cyclo);
            currentMethod.setSloc(sloc);
            methods.add(currentMethod);
     
            
        }
     
    }

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public MethodManager getMethodmanager() {
	return methodmanager;
}

public void setMethodmanager(MethodManager methodmanager) {
	this.methodmanager = methodmanager;
}

public List<ResultMethod> getResultmethod() {
	return resultmethod;
}

public void setResultmethod(List<ResultMethod> resultmethod) {
	this.resultmethod = resultmethod;
}

public static void main(String[] args) {
	MethodMetrics p=new MethodMetrics();
	/*MethodManager bla = new MethodManager();
	List<ResultMethod> methods = bla.list((long) 86);
	int i=0;
	for(ResultMethod res : methods){
		i++;
	}
	System.out.println(i);
*/
}
	
}
